use anyhow::Result;
use serde::{Deserialize, Serialize};

use hyper::{Request, Client, body};
use hyper::client::HttpConnector;

use std::borrow::Borrow;

#[derive(Debug, Serialize, Deserialize)]
pub struct JsonRpcError {
    pub code: u32,
    pub message: String,
    pub data: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct JsonRpcResponse<T> {
    pub id: u32,
    pub jsonrpc: String,
    pub result: Option<T>,
    pub error: Option<JsonRpcError>,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename = "SectorID")]
pub struct SectorId {
    #[serde(rename = "PascalCase")]
    pub miner: u64,
    #[serde(rename = "PascalCase")]
    pub number: u64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct SectorStatus {
    #[serde(rename(deserialize = "SectorID"))]
    pub sector_id: u64,
    pub state: String,
}

pub async fn query_sector_status(client: &Client<HttpConnector>, url: &str, token: &str, sector: u64) -> Result<JsonRpcResponse<SectorStatus>>{
    let body = serde_json::json!({
        "jsonrpc": "2.0",
	    "method": "Filecoin.SectorsStatus",
	    "params": [sector, false],
	    "id": 1
    });
    let auth = format!("Bearer {}", token);
    let body = body::Body::from(body.to_string());

    let request = Request::builder()
        .uri(url)
        .header("Authorization", auth)
        .body(body)?;

    let rsp = client.request(request).await?;
    if rsp.status().is_success() {
        let buf = body::to_bytes(rsp).await?;
        let result: JsonRpcResponse<SectorStatus> = serde_json::from_slice(buf.borrow())?;
        Ok(result)
    } else {
        Err(anyhow::Error::msg(format!("http request got error response {}", rsp.status())))
    }
}